#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文件中转站 Web 应用
提供文件上传、下载、列表查看、删除等功能
"""

import os
import json
import time
from datetime import datetime
from werkzeug.utils import secure_filename
from werkzeug.exceptions import RequestEntityTooLarge
from flask import Flask, request, jsonify, send_from_directory, render_template

# 创建Flask应用实例
app = Flask(__name__)

# 应用配置
app.config['SECRET_KEY'] = 'your-secret-key-here'  # 用于会话加密
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024  # 限制上传文件大小为500MB
app.config['UPLOAD_FOLDER'] = 'uploads'  # 上传文件存储目录

# 允许上传的文件类型
ALLOWED_EXTENSIONS = {
    'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx', 
    'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', '7z', 'mp3', 
    'mp4', 'avi', 'mov', 'mkv', 'py', 'js', 'html', 'css'
}

def allowed_file(filename):
    """检查文件是否为允许的类型"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def get_file_size(filepath):
    """获取文件大小（字节）"""
    try:
        return os.path.getsize(filepath)
    except OSError:
        return 0

def format_file_size(size_bytes):
    """格式化文件大小显示"""
    if size_bytes == 0:
        return "0 B"
    size_names = ["B", "KB", "MB", "GB"]
    import math
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return f"{s} {size_names[i]}"

def ensure_upload_folder():
    """确保上传目录存在"""
    if not os.path.exists(app.config['UPLOAD_FOLDER']):
        os.makedirs(app.config['UPLOAD_FOLDER'])

@app.route('/')
def index():
    """主页路由 - 返回前端界面"""
    return render_template('index.html')

@app.route('/api/upload', methods=['POST'])
def upload_file():
    """文件上传API接口"""
    try:
        # 检查是否有文件被上传
        if 'file' not in request.files:
            return jsonify({'success': False, 'message': '没有选择文件'}), 400
        
        file = request.files['file']
        
        # 检查文件名是否为空
        if file.filename == '':
            return jsonify({'success': False, 'message': '没有选择文件'}), 400
        
        # 检查文件类型是否允许
        if not allowed_file(file.filename):
            return jsonify({
                'success': False, 
                'message': f'不支持的文件类型。支持的类型：{", ".join(ALLOWED_EXTENSIONS)}'
            }), 400
        
        # 确保上传目录存在
        ensure_upload_folder()
        
        # 安全处理文件名
        filename = secure_filename(file.filename)
        
        # 如果文件已存在，添加时间戳避免冲突
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if os.path.exists(filepath):
            name, ext = os.path.splitext(filename)
            timestamp = str(int(time.time()))
            filename = f"{name}_{timestamp}{ext}"
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        
        # 保存文件
        file.save(filepath)
        
        # 获取文件信息
        file_size = get_file_size(filepath)
        upload_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        
        return jsonify({
            'success': True,
            'message': '文件上传成功',
            'file_info': {
                'filename': filename,
                'size': format_file_size(file_size),
                'upload_time': upload_time
            }
        })
        
    except RequestEntityTooLarge:
        return jsonify({
            'success': False, 
            'message': '文件太大，最大支持500MB'
        }), 413
    except Exception as e:
        return jsonify({
            'success': False, 
            'message': f'上传失败：{str(e)}'
        }), 500

@app.route('/api/files', methods=['GET'])
def list_files():
    """获取文件列表API接口"""
    try:
        ensure_upload_folder()
        
        files_info = []
        
        # 遍历上传目录中的所有文件
        for filename in os.listdir(app.config['UPLOAD_FOLDER']):
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            
            # 只处理文件，忽略目录
            if os.path.isfile(filepath):
                file_size = get_file_size(filepath)
                # 获取文件修改时间
                mtime = os.path.getmtime(filepath)
                upload_time = datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
                
                files_info.append({
                    'filename': filename,
                    'size': format_file_size(file_size),
                    'size_bytes': file_size,
                    'upload_time': upload_time
                })
        
        # 按上传时间降序排列（最新的在前面）
        files_info.sort(key=lambda x: x['size_bytes'], reverse=True)
        
        return jsonify({
            'success': True,
            'files': files_info,
            'total_count': len(files_info)
        })
        
    except Exception as e:
        return jsonify({
            'success': False, 
            'message': f'获取文件列表失败：{str(e)}'
        }), 500

@app.route('/api/download/<filename>')
def download_file(filename):
    """文件下载API接口"""
    try:
        # 安全处理文件名
        safe_filename = secure_filename(filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], safe_filename)
        
        # 检查文件是否存在
        if not os.path.exists(filepath):
            return jsonify({
                'success': False, 
                'message': '文件不存在'
            }), 404
        
        # 发送文件
        return send_from_directory(
            app.config['UPLOAD_FOLDER'], 
            safe_filename, 
            as_attachment=True
        )
        
    except Exception as e:
        return jsonify({
            'success': False, 
            'message': f'下载失败：{str(e)}'
        }), 500

@app.route('/api/delete/<filename>', methods=['DELETE'])
def delete_file(filename):
    """文件删除API接口"""
    try:
        # 安全处理文件名
        safe_filename = secure_filename(filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], safe_filename)
        
        # 检查文件是否存在
        if not os.path.exists(filepath):
            return jsonify({
                'success': False, 
                'message': '文件不存在'
            }), 404
        
        # 删除文件
        os.remove(filepath)
        
        return jsonify({
            'success': True,
            'message': '文件删除成功'
        })
        
    except Exception as e:
        return jsonify({
            'success': False, 
            'message': f'删除失败：{str(e)}'
        }), 500

@app.errorhandler(413)
def too_large(e):
    """处理文件过大错误"""
    return jsonify({
        'success': False, 
        'message': '文件太大，最大支持500MB'
    }), 413

@app.errorhandler(404)
def not_found(e):
    """处理404错误"""
    return jsonify({
        'success': False, 
        'message': '请求的资源不存在'
    }), 404

@app.errorhandler(500)
def internal_error(e):
    """处理服务器内部错误"""
    return jsonify({
        'success': False, 
        'message': '服务器内部错误'
    }), 500

if __name__ == '__main__':
    # 确保上传目录存在
    ensure_upload_folder()
    
    # 启动开发服务器
    print("🚀 文件中转站启动中...")
    print("📁 上传目录：", os.path.abspath(app.config['UPLOAD_FOLDER']))
    print("🌐 访问地址：http://localhost:5000")
    
    app.run(debug=True, host='0.0.0.0', port=5000)